<?php
class Widget_GoogleCalendar_Calendar
{
  const BASEURL = "http://www.google.com/calendar/feeds/";
  
  protected
    $src,
    $opt;
  
  //----------------------------------------------------------------------------
  
  public function __construct($url)
  {
    $this->opt = array();
    $this->src = $this->fixUrl($url);
  }
  
  public function getUrl()
  {
    return strlen($params = implode('&', $this->opt)) ? "{$this->src}?$params" : $this->src;
  }
  
  public function addOption($key, $value = 'true')
  {
    $this->opt[$key] = "$key=$value";
  }
  
  public function removeOption($key)
  {
    if (isset($this->opt[$key]))
      unset($this->opt[$key]);
  }
  
  public function getEvents($limit = null)
  {
    $events = array();
    $api = new clAPI($this->getUrl());
    
    if ($api->parse())
    {
      foreach ($api->get('entry', $limit) as $eventNode)
      {
        $event = new Widget_GoogleCalendar_Event();
        
        $event->title       = (string) $eventNode->get('title');
        $event->description = (string) $eventNode->get('content');
        $event->location    = (string) $eventNode->get('gd:where@valueString');
        $event->status      = substr($v = (string) $eventNode->get('gd:eventStatus@value'), strpos($v, '#')+1);
        
        // Event date
        $start = (string) $eventNode->get('gd:when@startTime');
        $end   = (string) $eventNode->get('gd:when@endTime');
        
        $sdate = Date::getInstance($start);
        $edate = Date::getInstance($end);
        
        $hasTimePart = (bool) (count(explode('T', $start)) == 2);
        $isSingleDay = (bool) (($edate->diff($sdate, Time::DAY) == 0) || (($edate->diff($sdate, Time::DAY) == 1) && !$hasTimePart));
        
        if (strlen($tmp = (string) $eventNode->get('gd:when@valueString')))
          $event->dateDescription = $tmp;
        
        $event->hasTimePart = $hasTimePart;
        
        switch (true)
        {
          case $isSingleDay && !$hasTimePart:
            $event->type  = 'full';
            $event->start = $sdate;
            $event->end   = false;
            break;
          case !$isSingleDay && $hasTimePart:
            $event->type  = 'multiple';
            $event->start = $sdate;
            $event->end   = $edate;
            break;
          case !$isSingleDay && !$hasTimePart:
            $event->type  = 'multiple-full';
            $event->start = $sdate;
            $event->end   = $edate;
            break;
          case $isSingleDay && $hasTimePart:
          default:
            $event->type  = 'single';
            $event->start = $sdate;
            $event->end   = $edate;
            break;
        }
        
        $events[] = $event;
      }
    }
    
    return $events;
  }
  
  //----------------------------------------------------------------------------
  
  public function minDate($d)
  {
    $this->opt['start-min'] = "start-min=$d";
  }
  
  public function maxDate($d)
  {
    $this->opt['start-max'] = "start-max=$d";
  }
  
  public function timeZone($tz = 'Europe/Madrid')
  {
    try { new DateTimeZone($tz); }
    catch (Exception $e) { $tz = 'Europe/Madrid'; }
    $this->opt['ctz'] = "ctz=$tz";
  }
  
  //----------------------------------------------------------------------------
  
  public function maxResults($n)
  {
    $this->opt['max-results'] = "max-results=$n";
  }
  
  public function orderByStartTime()
  {
    $this->opt['orderby'] = "orderby=starttime";
  }
  
  public function orderByLastModified()
  {
    $this->opt['orderby'] = "orderby=lastmodified";
  }
  
  public function ascendingOrder()
  {
    $this->opt['sortorder'] = "sortorder=a";
  }
  
  public function descendingOrder()
  {
    $this->opt['sortorder'] = "sortorder=d";
  }
  
  //----------------------------------------------------------------------------
  
  private function fixUrl($url)
  {
    $parts = explode('?', $url);
    
    // Parameters
    if (2 == count($parts))
    {
      foreach (explode('&', $parts[1]) as $param)
      {
        $this->opt[array_shift(explode('=', $param))] = $param;
      }
    }
    
    // Add singleevents as true
    $this->opt['singleevents'] = 'singleevents=true';
    
    // return full version
    return preg_replace('~\/basic$~', '/full', $parts[0]);
  }
}

